
# Eventually, I should merge this class as a subclass from GameScreen.
include Globals
class StarFleet < Screen
  attr_reader :game_options, :players
  WARP_SPOTS = [[WIDTH/2 - 50, HEIGHT/2 - 50],
    [WIDTH/2 + 50, HEIGHT/2 - 50],
    [WIDTH/2 - 50, HEIGHT/2 + 50],
    [WIDTH/2 + 50, HEIGHT/2 + 50]
  ]

  def initialize(window, options)
    super(window)
    @window = window
    @game_options = options
    @fleet = []
    @objects = []
    @tasks = []
    @speedometers = []
    @powerups = []
    @asteroids = []
    @enemies = []
    @button_actions = {"Accelerate" => :accelerate, "Reverse" => :reverse,
      "Turn Left" => :turn_left, "Turn Right" => :turn_right,
      "Shoot" => :shoot }
    begin
      @music = Song.new(window, "soundfx/game_play.ogg")
    rescue
      @game_options["music"] = false
      puts "music failed to load"
    end
    @music.volume = 0.5 if @music
    @background = window.images["comet_bckgrnd.png"]
    @backgrounds = ["nebula", "atmosphere", "alien", "satan", "far_out",
      "old_school", "old_sound"]

    @level = 1
    @fleet_score = 0
    @players = []
    @display = Font.new(window, Gosu.default_font_name, 30) # level number
    @hap_font = Font.new(window, Gosu.default_font_name, 60)
    @game_over = false
    start_level
  end

  def check_buttons
    @fleet.each do |ship|
      @window.game_controls[0].each do |action, button|
        if @window.button_down? button
          ship.method(@button_actions[action]).call
        end
      end
    end
    # cycles the action to every ship in the fleet
  end

  def update
    check_buttons
    @objects.reject! { |obj| !obj.update }
    @tasks.reject! { |task| !task.tick }
    @fleet.reject! { |ship| ship.is_dead }
    @music.play unless @music.playing? or @game_options['music'] == false or @active == false
    game_over if @fleet.empty?
    end_level if @asteroids.empty?
    check_collision
  end

  def check_collision
    @objects.each do |obj|
      id = obj.obj_id
      case id
      when "blue_bullet" 
        @asteroids.each do |oid|
          if oid.check(obj.x, obj.y, 27) 
            @fleet_score += 1
            obj.vanish
          end
        end
        @enemies.each do |enemy|
          if enemy.check(obj.x, obj.y, 30) 
            @fleet_score += 3
            obj.vanish
          end
        end
      when :enemy_bullet
        @fleet.each { |ship| ship.check(obj.x, obj.y, 25) }
      when "asteroid"
        @fleet.each {|ship| ship.check(obj.x, obj.y, 40 * obj.factor)}
        @enemies.each {|enemy| enemy.check(obj.x, obj.y, 45 * obj.factor) }
      when :comet
        @fleet.each {|ship| ship.check(obj.x, obj.y, 65) }
        @asteroids.each {|oid| oid.check(obj.x, obj.y, 65 * 1.0/oid.factor) }
        @enemies.each {|enemy| enemy.check(obj.x, obj.y, 65) }
      end
    end
  end

  def button_down(id)
    # Exit the game with Esc key
    case id
    when Button::KbEscape
      kill
    when Button::KbReturn
      Pause.new(@window, self)
    end
  end

  def draw
    @background.draw(0, 0, BACKGROUND_Z)
    @objects.each { |obj| obj.draw }
    @display.draw_rel(@level_text, WIDTH/2, 20, TEXT_Z, 0.5, 0.5)
    @hap_font.draw_rel(@hap_text, WIDTH/2, HEIGHT/2, TEXT_Z, 0.5, 0.5)
    @score_text.draw_rot(WIDTH/2, HEIGHT/2, TEXT_Z, 0) if @score_text
  end

  def start_level
    @transitioning = false
    @objects = []
    @tasks = []
    @asteroids = []
    @enemies = []
    @level_text = "Level #{@level}"
    game_start
    @music.play if @game_options["music"] and @game_options['mode'] != :co_op
    reset_fleet
  end

  def game_start
    (@level - 2).times do
      Task.new(self, @window, :wait => rand(6000) + 400) { Enemy.new(self, @window) }
    end
    (@level - 6).times do |i|
      Task.new(self, @window, :wait => (i+1) * 1500) {Comet.new(self, @window)}
    end
    @hap_text = "Level #{@level}"
    Task.new(self, @window, :wait => 120) { @hap_text = "" }
    mode = 0 # the image mode
    mode = 1 if @level >= 5
    mode = 2 if @level >= 10
    mode = 3 if @level >= 15
    mode = 4 if @level >= 20
    mode = 5 if @level >= 25
    mode = 6 if @level >= 30
    @background = @window.images["../3d_renders/background_#{@backgrounds[mode]}.png"]
    ((@level + 2) / 2).times do
      Asteroid.new_asteroid(self, @window, mode, 0, 0, :large)
      Asteroid.new_asteroid(self, @window, mode, 0, 0, :normal)
    end
  end

  def reset_fleet
    @fleet = []
    4.times { @fleet << Player.new(@window, self, :blue) }
    @fleet.each { |ship| ship.lives = 1 }
    @players = @fleet # just for the enemy's targetting reference
    #build the fleet
    @fleet.each_with_index do |ship, i|
      ship.vel_x = ship.vel_y = ship.current_speed = 0
      ship.normalize
      ship.deaths = 0
      ship.lives = 1
      ship.warp_to(WARP_SPOTS[i][0], WARP_SPOTS[i][1], false)
    end
  end

  def end_level
    return if @transitioning
    @hap_text = "Level Completed"
    @fleet.each {|ship| ship.level_end }
    Task.new(self, @window, :wait => 120) do
      @level += 1
      @hap_text = ""
      @transitioning = false
      start_level
    end
  end

  def game_over
    return if @game_over
    @hap_text = "GAME OVER"
    @game_over = true
    Task.new(self, @window, :wait => 300) { kill }
  end

  def kill
    @active = false
    @music.stop if @music.playing?
  end

  def ended?
    !@active
  end

  def add_task(task)
    @tasks << task
  end

  def add_object(obj)
    @objects << obj
  end

  def add_asteroid(asteroid)
    @asteroids << asteroid
  end

  def add_powerup(powerup)
    #@powerups << powerup
    # nope, nope, only in star fleet chaos, soon to come.
  end

  def remove_asteroid(asteroid)
    @asteroids -= [asteroid]
  end

  def add_enemy(enemy)
    @enemies << enemy
  end

  def remove_enemy(enemy)
    @enemies -= [enemy]
  end

end
